#ifndef _DOFS_H_
#define _DOFS_H_

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define fatal(fmt, arg...) \
    do { \
        printf("[fatal] %s +%d : " fmt "\n", __FILE__, __LINE__, ## arg); \
        exit(1); \
    } while(0)

static int dofs_info_on = 0;

#define dofs_info(fmt, arg...) \
    if (dofs_info_on) { \
        printf("[dofs] " fmt "\n", ## arg); \
    }

static inline int set_str(const char *file, char *str)
{
    int fd = open(file, O_WRONLY);
    if (fd < 0) {
        dofs_info("can't open: %s", file);
        return -1;
    }

    int ret = write(fd, str, strlen(str));
    if (ret < 0) {
        dofs_info("can't open: %s", file);
        return -1;
    }

    close(fd);
    return 0;
}

static inline int get_str(const char *file, char *str, int len)
{
    int fd = open(file, O_RDONLY);
    if (fd < 0) {
        dofs_info("can't open: %s", file);
        return -1;
    }

    int ret = read(fd, str, len - 1);
    if (ret < 0) {
        dofs_info("can't open: %s", file);
        return -1;
    }

    str[ret] = '\0';

    close(fd);

    return ret;
}

static inline int set_int(const char *file, int64_t value)
{
    char buf[32] = {0}; // uint(-1): 4294967295
                        //
    if (snprintf(buf, sizeof(buf), "%ld\n", value) < 0) {
        dofs_info("sprintf: value=%ld", value);
        return -1;
    }

    if (set_str(file, buf))
        return -1;

    return 0;
}

static inline int get_int(const char *file, int64_t *value)
{
    char buf[32] = {0};
    if (get_str(file, buf, sizeof(buf)))
        return -1;
    *value = atoll(buf);
    return 0;
}

static inline int is_dir(const char *entry)
{
    struct stat st = {0};
    if (stat(entry, &st) == 0) {
        return S_ISDIR(st.st_mode) ? 1 : 0;
    }
    return -1;
}

static inline int is_file(const char *entry)
{
    struct stat st = {0};
    if (stat(entry, &st) == 0) {
        return S_ISREG(st.st_mode) ? 1 : 0;
    }
    return -1;
}

#include <dirent.h>

static inline int ls_dir(const char *entry)
{
    DIR *dir;
    struct dirent *dirent;

    // 打开目录
    dir = opendir(entry);
    if (dir == NULL) {
        fatal("can't open dir: %s", entry);
    }

    // 遍历目录
    while ((dirent = readdir(dir)) != NULL) {
        printf("%s\n", dirent->d_name);
    }

    // 关闭目录
    closedir(dir);

    return 0;
}

#endif
